/*=============================================================================

  SONY CAM HAL MODULE

  FILE: hw_sony_cam_sync.c
  
  DESCRIPTION

    SONY CAM HAL Module

  Copyright (c) DaeSung Engineering Inc. All rights reserved.

=============================================================================*/
/*=============================================================================

  EDIT HISTORY

  ---------  -------  -------------------------------------------------------
    when        who          what, where, why
  ---------  -------  -------------------------------------------------------
   13/10/14   jyko         Initial version

=============================================================================*/


 /*=============================================================================
  HEADER INCLUSION
=============================================================================*/
#include "hw_sony_cam_mod.h"
#include <string.h>
#include <stdio.h>


/*=============================================================================
  CONSTANT DEFINITION
=============================================================================*/
// COMMAND LIST
typedef enum
{
	CAM_CMD_NONE = 0,

	CAM_READY_C,

	CAM_GAIN_C,
	CAM_GAINF_C,	// Gain Fine-Tunes
	CAM_PED_C,
	CAM_SHT_C,
	CAM_TRGM_C,
	CAM_TRGP_C,
	CAM_WB_C,
	CAM_RGAIN_C,
	CAM_BGAIN_C,
	CAM_AWB_C,
	CAM_SHP_C,
	CAM_DTL_C,
	CAM_GAM_C,
	CAM_GBIN_C,
	CAM_BINN_C,
	CAM_EXT_C,
	CAM_COLB_C,
	CAM_GRY_C,
	CAM_BRT_C,

	CAM_PAR_C,
	CAM_COLM_C,
	CAM_DTLC_C,
	CAM_DTLT_C,
	CAM_DTLS_C,
	CAM_DTLL_C,
	
	CAM_VER_C
} CAM_RXCMD;

/*=============================================================================
  LOCALIZED FUNCTION DEFINITION
=============================================================================*/
static void recv_INT1(cam_s *cam);
static void recv_INT2(cam_s *cam);
static void recv_INT3(cam_s *cam);
static void recv_VER(cam_s *cam);

/*=============================================================================
  EXTERNALIZED FUNCTION DEFINITION
=============================================================================*/
static void scom_recv_sync(cam_s *cam);

//---------------------------------------------------------
// STRING PARSING
//---------------------------------------------------------
void scom_rx_sync(cam_s *cam, char *ptr, int32 len)
{
	tx_s			*tx = cam->tx;
	rx_s			*rx = cam->rx;

#if 0
	scom_rx_trace(ptr, len);
#endif

	while(len>0)
	{
		switch(rx->state)
		{
		case RX_NONE_S:
		case RX_IDLE_S:
		{
			//if((*ptr) == RX_SRX)
			{
				rx_add(rx, *ptr);
				rx_state_set(rx, RX_RECV_S);
			}
			break;
		}
		case RX_RECV_S:
		{
			if(rx_add(rx, *ptr) == FALSE)
			{
				rx_clear(rx);
				break;
			}
			if((*ptr) == RX_ERX2)
			{
				scom_recv_sync(cam);

				rx_clear(rx);
				rx_state_set(rx, RX_IDLE_S);
				
				// Say to Task
				tx_state_off(tx, TX_SYNC_S);
				Sync_Set(cam->sync, TRUE);
				Task_Switch();
			}
			break;
		}
		}
		ptr++; len--;
	}
}

//---------------------------------------------------------
// STRING ANALYSIS
//---------------------------------------------------------
static dword sync_cmd(cam_s *cam);
static void sync_mean(cam_s *cam);
static boolean sync_ready_check(cam_s *cam);
void scom_recv_sync(cam_s *cam)
{
	dword		cmd;

	//DBGPRINT("\n[scom_recv_sync] ========================\n");
#if 1
	rx_print(cam->rx);
#endif

	cmd = sync_cmd(cam);
	
	if(cmd != CAM_CMD_NONE)
	{
		sync_mean(cam);
	}

	switch(cmd)
	{
	case CAM_GAIN_C: 	recv_INT1(cam); 	break;
	case CAM_GAINF_C: 	recv_INT1(cam); 	break;
	case CAM_PED_C: 	recv_INT1(cam); 	break;
	case CAM_SHT_C: 	recv_INT1(cam); 	break;
	case CAM_TRGM_C: 	recv_INT1(cam); 	break;
	case CAM_TRGP_C: 	recv_INT1(cam); 	break;
	case CAM_WB_C: 		recv_INT1(cam); 	break;
	case CAM_RGAIN_C: 	recv_INT1(cam); 	break;
	case CAM_BGAIN_C: 	recv_INT1(cam); 	break;
	case CAM_AWB_C:	recv_INT1(cam);		break;
	case CAM_SHP_C:		recv_INT1(cam);		break;
	case CAM_DTL_C:		recv_INT1(cam);		break;
	case CAM_GAM_C:	recv_INT1(cam);		break;
	case CAM_GBIN_C:	recv_INT1(cam);		break;
	case CAM_BINN_C:	recv_INT1(cam);		break;
	case CAM_EXT_C:		recv_INT1(cam);		break;
	case CAM_COLB_C:	recv_INT1(cam);		break;
	case CAM_GRY_C:	recv_INT1(cam);		break;
	case CAM_BRT_C:		recv_INT1(cam);		break;
	case CAM_PAR_C:		recv_INT3(cam);		break;
	case CAM_COLM_C:	recv_INT3(cam);		break;
	case CAM_DTLC_C:	recv_INT3(cam);		break;
	case CAM_DTLT_C:	recv_INT2(cam);		break;
	case CAM_DTLS_C:	recv_INT2(cam);		break;
	case CAM_DTLL_C:	recv_INT2(cam);		break;
	case CAM_VER_C:		recv_VER(cam);		break;
	case CAM_READY_C:
	{
		if(sync_ready_check(cam))
		{
//			DBGPRINT("[READY]\n");
		}
		else
		{
//			DBGPRINT("[CAM_CMD_NONE]\n");
		}
		break;
	}
	}

//	DBGPRINT("========================\n\n");
	
	return;
}

void sync_mean(cam_s *cam)
{
	tx_s		*tx = cam->tx;
	rx_s		*rx = cam->rx;
	char		*ptr, *src, *dst;
	int32	tx_len, j;

	memZeros(rx->mean, rx->len);

	ptr = tx->ptr;
	src = rx->ptr;
	dst = rx->mean;

	tx_len = strlen(ptr);

	for(j=0; j<rx->len_recv; j++, src++)
	{
		if(j < tx_len)
		{
			if((*ptr++) == (*src))
			{
                		continue; // echo value
			}
		}
		if(((*src) == RX_ERX1) || ((*src) == RX_ERX2))
		{
			break;
		}
		else
		{
			*dst = *src;
			dst++;
		}
	}
	//DBGPRINT("========= sync_mean(%s)\n", rx->mean);
}

boolean sync_ready_check(cam_s *cam)
{
	rx_s		*rx = cam->rx;
	char		*src, *dst;
	int32	j;

	memZeros(rx->mean, rx->len);

	src = rx->ptr;
	dst = rx->mean;

	for(j=0; j<rx->len_recv; j++, src++)
	{
		if(((*src) == RX_ERX1) || ((*src) == RX_ERX2))
		{
			break;
		}
		else
		{
			*dst = *src;
			dst++;
		}
	}
	if(strcmp(rx->mean, "OK") == 0)
	{
		return	TRUE;
	}
	
	return	FALSE;
}
/*=============================================================================
  COMMAND PARSING ROUTINE
=============================================================================*/
//---------------------------------------------------------
// GET COMMAND
//---------------------------------------------------------
static boolean sync_is_matched(tx_s *tx, rx_s *rx);
dword sync_cmd(cam_s *cam)
{
	rx_s		*rx = cam->rx;
	tx_s		*tx = cam->tx;

	if(sync_is_matched(tx, rx) == FALSE)
	{
		DBGPRINT("MIS-MATCHED\n");
		return	CAM_CMD_NONE;
	}

	memZeros(rx->tmp, rx->len);
	memCopy(rx->tmp, rx->ptr, rx->len);

	if(strcmp(rx->tmp, "GAIN-STEP") == 0)
	{
		return	CAM_GAIN_C;
	}
	if(strcmp(rx->tmp, "GAIN-FINE") == 0)
	{
		return	CAM_GAINF_C;
	}
	if(strcmp(rx->tmp, "PEDESTAL") == 0)
	{
		return	CAM_PED_C;
	}
	if(strcmp(rx->tmp, "SHUTTER") == 0)
	{
		return	CAM_SHT_C;
	}
	if(strcmp(rx->tmp, "TRG-MODE") == 0)
	{
		return	CAM_TRGM_C;
	}
	if(strcmp(rx->tmp, "TRG-POL") == 0)
	{
		return	CAM_TRGP_C;
	}
	if(strcmp(rx->tmp, "WBMODE") == 0)
	{
		return	CAM_WB_C;
	}
	if(strcmp(rx->tmp, "RGAIN") == 0)
	{
		return	CAM_RGAIN_C;
	}
	if(strcmp(rx->tmp, "BGAIN") == 0)
	{
		return	CAM_BGAIN_C;
	}
	if(strcmp(rx->tmp, "AWBWINDOW") == 0)
	{
		return	CAM_AWB_C;
	}
	if(strcmp(rx->tmp, "SHARP") == 0)
	{
		return	CAM_SHP_C;
	}
	if(strcmp(rx->tmp, "DTL-MODE") == 0)
	{
		return	CAM_DTL_C;
	}
	if(strcmp(rx->tmp, "GAMMA") == 0)
	{
		return	CAM_GAM_C;
	}
	if(strcmp(rx->tmp, "BINARIZE") == 0)
	{
		return	CAM_GBIN_C;
	}
	if(strcmp(rx->tmp, "BINNING") == 0)
	{
		return	CAM_BINN_C;
	}
	if(strcmp(rx->tmp, "EXTTRG") == 0)
	{
		return	CAM_EXT_C;
	}
	if(strcmp(rx->tmp, "COLORBAR") == 0)
	{
		return	CAM_COLB_C;
	}
	if(strcmp(rx->tmp, "GRAYSCALE") == 0)
	{
		return	CAM_GRY_C;
	}
	if(strcmp(rx->tmp, "BRATE") == 0)
	{
		return	CAM_BRT_C;
	}
	if(strcmp(rx->tmp, "PARTIAL") == 0)
	{
		return	CAM_PAR_C;
	}
	if(strcmp(rx->tmp, "COLORMTX") == 0)
	{
		return	CAM_COLM_C;
	}
	if(strcmp(rx->tmp, "DTL-COEF") == 0)
	{
		return	CAM_DTLC_C;
	}
	if(strcmp(rx->tmp, "DTL-TH") == 0)
	{
		return	CAM_DTLT_C;
	}
	if(strcmp(rx->tmp, "DTL-SCL") == 0)
	{
		return	CAM_DTLS_C;
	}
	if(strcmp(rx->tmp, "DTL-LVL") == 0)
	{
		return	CAM_DTLL_C;
	}
	if(strcmp(rx->tmp, "VERSION") == 0)
	{
		return	CAM_VER_C;
	}
	return	CAM_READY_C;
}

//---------------------------------------------------------
// 1 PARAMETER RECEIVE
//---------------------------------------------------------
void recv_INT1(cam_s *cam)
{
	rx_s			*rx = cam->rx;
	tx_s			*tx = cam->tx;
	scom_val_s	*val;
	dword		type;
	int32		n;
		
	type = tx_type(tx);
	val = &tx->val;

	//DBGPRINT("[recv_INT1] <%s>\n", rx->mean);
	
	if(ISMASKON(type, TX_QUERY_T) != TRUE)
	{
		return;
	}

	n = strlen(rx->mean);
	if(n < 1)
	{
		val->ack = FALSE;
	}
	else
	{
		if(strstr(rx->mean, "ERROR") != NULL)
		{
			val->ack = FALSE;
		}
		else
		{
			val->nval1 = atoi(rx->mean);
			val->ack = TRUE;
		}
	}
}

//---------------------------------------------------------
// 2 PARAMETER RECEIVE
//---------------------------------------------------------
void recv_INT2(cam_s *cam)
{
	rx_s			*rx = cam->rx;
	tx_s			*tx = cam->tx;
	scom_val_s	*val;
	dword		type;
	int32		k, j, n;
	int32		tmp;
	char			*ptr;
		
	type = tx_type(tx);
	val = &tx->val;

	//DBGPRINT("[recv_INT2] <%s>\n", rx->mean);
	
	if(ISMASKON(type, TX_QUERY_T) != TRUE)
	{
		return;
	}
	
	ptr = rx->mean;
	if(strstr(ptr, "ERROR") != NULL)
	{
		return;
	}
	
	for(k=0; k<2; k++)
	{
		memZeros(rx->tmp, rx->len);

		n = strlen(ptr);
		for(j=0; j<n; j++, ptr++)
		{
			if((*ptr) == ',')
			{
				ptr++;
				break;
			}
			*(rx->tmp + j) = *ptr;
		}
		n = strlen(rx->tmp);
		if(n < 1)
		{
			val->ack = FALSE;
			return;
		}
		tmp = (boolean)atoi(rx->tmp);

		switch(k)
		{
		case 0: val->nval1 = tmp; break;
		case 1: val->nval2 = tmp; break;
		}
	}
	val->ack = TRUE;
}

//---------------------------------------------------------
// 3 PARAMETER RECEIVE
//---------------------------------------------------------
void recv_INT3(cam_s *cam)
{
	rx_s			*rx = cam->rx;
	tx_s			*tx = cam->tx;
	scom_val_s	*val;
	dword		type;
	int32		k, j, n;
	int32		tmp;
	char			*ptr;
		
	type = tx_type(tx);
	val = &tx->val;

	//DBGPRINT("[recv_INT3] <%s>\n", rx->mean);
	
	if(ISMASKON(type, TX_QUERY_T) != TRUE)
	{
		return;
	}
	
	ptr = rx->mean;
	if(strstr(ptr, "ERROR") != NULL)
	{
		return;
	}
	
	for(k=0; k<3; k++)
	{
		memZeros(rx->tmp, rx->len);

		n = strlen(ptr);
		for(j=0; j<n; j++, ptr++)
		{
			if((*ptr) == ',')
			{
				ptr++;
				break;
			}
			*(rx->tmp + j) = *ptr;
		}
		n = strlen(rx->tmp);
		if(n < 1)
		{
			val->ack = FALSE;
			return;
		}
		tmp = (boolean)atoi(rx->tmp);

		switch(k)
		{
		case 0: val->nval1 = tmp; break;
		case 1: val->nval2 = tmp; break;
		case 2: val->nval3 = tmp; break;
		}
	}
	val->ack = TRUE;
}

//---------------------------------------------------------
// VER
//---------------------------------------------------------
void recv_VER(cam_s *cam)
{
	rx_s			*rx = cam->rx;
	tx_s			*tx = cam->tx;
	scom_val_s			*val = &tx->val;
	int32		n;

	n = strlen(rx->mean);
	if(n < 1)
	{
		val->ack = FALSE;
	}
	else
	{
		strcpy(cam->ver, rx->mean);
		val->ack = TRUE;
	}
}

//---------------------------------------------------------
// CHECK TX & RX MATCHED OR NOT
//---------------------------------------------------------
static boolean recv_is_tx_avail(tx_s *tx);
static boolean recv_is_rx_avail(rx_s *rx);
boolean sync_is_matched(tx_s *tx, rx_s *rx)
{
	dword		type;
	int32		len_tx, len_rx, len, je, j;
	
	if(recv_is_tx_avail(tx) == FALSE)
		return	FALSE;

	if(recv_is_rx_avail(rx) == FALSE)
		return	FALSE;

	type = tx_type(tx);

	len_tx = strlen(tx->ptr);
	len_rx = rx->len_recv;
	len = MIN(len_tx, len_rx);

//	DBGPRINT("tx_len = %d\n", len_tx);
//	DBGPRINT("rx_len = %d\n", len_rx);
	
	
	/*		----------------------2013. 10. 15. jyko
	if(ISMASKON(type, TX_QUERY_T))
	{
		if((*(tx->ptr + CMD_QUERY)) != TX_QUERY)
		{
			return	FALSE;
		}
		je = TX_QUERY_T-1;
	}
	else
	*/
	{
		je = len - 1; // except ETX1,2
	}

	for(j=0; j<je; j++)
	{
		if((*(tx->ptr+j)) != (*(rx->ptr+j)))
		{
			return	FALSE;
		}
	}
	
	return	TRUE;
}

boolean recv_is_tx_avail(tx_s *tx)
{
	int32			len;

	len = strlen(tx->ptr);

	if(len <TX_LEN_MIN)
	{
		return	FALSE;
	}

	if((*(tx->ptr+len-1)) != TX_ETX1)
	{
		return	FALSE;
	}

	return	TRUE;
}

boolean recv_is_rx_avail(rx_s *rx)
{
	int32		len;

	len = rx->len_recv;

	/*		----------------------2013. 10. 16. jyko
	if(rx->len_recv <RX_LEN_MIN)
	{
		return	FALSE;
	}
	*/

	if((*(rx->ptr+len-1)) != RX_ERX2)
	{
		return	FALSE;
	}

	return	TRUE;
}

/*--- END OF hw_sony_cam_sync.c ---*/
